import { PayloadAction, createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { InvoiceEntry, InvoiceType, calculateGrossProfit, calculateTotalAmount } from "./IssueInvoice";
import { removeElementFromArray } from "../util/Arrays";
import { RootState } from "./store";
import { getRequest } from "../util/Auth";
import { NulResponse, createRequest } from "./common";

interface InvoiceState {
  totalAmount: number;
  grossProfit: number;
  type: InvoiceType;
  entries: InvoiceEntry[];
  id: string;
  date: string;
}

interface ModifyInvoiceRequest {
  id: number;
  quantity: string;
}

interface IssueInvoiceRequestEntry {
  id: number;
  quantity: number;
}

interface UpdateInvoiceRequest {
  entries: IssueInvoiceRequestEntry[];
  type: InvoiceType;
  id: string;
}

interface ApproveInvoiceRequest {
  approve: boolean;
  id: string;
}

const invoiceInitialState: InvoiceState = {
  totalAmount: 0,
  grossProfit: 0,
  type: 'retail',
  entries: [],
  id: '',
  date: ''
};

export const updateInvoice = createAsyncThunk('api/updateInvoice', async (invoice: UpdateInvoiceRequest, { getState, rejectWithValue }) => {
  const state = getState() as RootState;
  try {
    const request = getRequest(state);
    const response = await request.post<NulResponse<null>>('/service/invoice/updateEntry', createRequest(invoice));
    return response.data;
  }
  catch (e) {
    return rejectWithValue(e);
  }
});

export const approveInvoice = createAsyncThunk('api/approveInvoice', async (invoice: ApproveInvoiceRequest, { getState, rejectWithValue }) => {
  const state = getState() as RootState;
  try {
    const request = getRequest(state);
    const response = await request.post<NulResponse<null>>('/service/invoice/approveEntry', createRequest(invoice));
    return response.data;
  }
  catch (e) {
    return rejectWithValue(e);
  }
}) 

const invoiceSlice = createSlice({
  name: 'invoice',
  initialState: invoiceInitialState,
  reducers: {
    addInvoice: (state, action: PayloadAction<InvoiceEntry>) => {
      const invoice: InvoiceEntry = action.payload;
      const index: number = state.entries.findIndex((value) => value.id === invoice.id);
      if (index !== -1) {
        state.entries[index].quantity += invoice.quantity;
      }
      else {
        state.entries.push(invoice);
      }
      state.totalAmount = calculateTotalAmount(state.entries, state.type);
      state.grossProfit = calculateGrossProfit(state.entries, state.type);
    },
    deleteInvoice: (state, action: PayloadAction<number>) => {
      const id: number = action.payload;
      const index: number = state.entries.findIndex((value) => value.id === id);
      if (index !== -1) {
        state.entries = removeElementFromArray(state.entries, index);
      }
      state.totalAmount = calculateTotalAmount(state.entries, state.type);
      state.grossProfit = calculateGrossProfit(state.entries, state.type);
    },
    modifyInvoice: (state, action: PayloadAction<ModifyInvoiceRequest>) => {
      const request: ModifyInvoiceRequest = action.payload;
      const index: number = state.entries.findIndex((value) => value.id === request.id);
      if (index !== -1) {
        state.entries[index].quantity = request.quantity;
      }
      state.totalAmount = calculateTotalAmount(state.entries, state.type);
      state.grossProfit = calculateGrossProfit(state.entries, state.type);
    }
  },
  extraReducers: (builder) => {
    builder.addCase(updateInvoice.rejected, (state, action) => {
      console.error(action.error);
    }).addCase(updateInvoice.fulfilled, (state, action) => {
      
    }).addCase(approveInvoice.rejected, (state, action) => {
      console.error(action.error);
    }).addCase(approveInvoice.fulfilled, (state, action) => {

    });
  }
});

export const { addInvoice, deleteInvoice, modifyInvoice } = invoiceSlice.actions;
export const selectInvoiceTotalAmount = (state: RootState) => state.invoiceReducer.totalAmount;
export const selectInvoiceGrossProfit = (state: RootState) => state.invoiceReducer.grossProfit;
export const selectInvoiceType = (state: RootState) => state.invoiceReducer.type;
export const selectInvoiceEntries = (state: RootState) => state.invoiceReducer.entries;
export default invoiceSlice.reducer;